import { renderToPipeableStream } from 'react-dom/server'
import semver from 'semver'

import BrowseApp from '../client/browse/App.js'
import MainTemplate from '../templates/MainTemplate.js'
import asyncHandler from '../utils/asyncHandler.js'
import getScripts from '../utils/getScripts.js'
import { createElement } from 'react'
import { getVersionsAndTags } from '../utils/npm.js'

const globalURLs =
  process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'staging'
    ? {
        '@emotion/react': '/@emotion/react@11.11.1/dist/emotion-react.umd.min.js',
        react: '/react@18.2.0/umd/react.production.min.js',
        'react-dom': '/react-dom@18.2.0/umd/react-dom.production.min.js'
      }
    : {
        '@emotion/react': '/@emotion/react@11.11.1/dist/emotion-react.umd.min.js',
        react: '/react@18.2.0/umd/react.development.js',
        'react-dom': '/react-dom@18.2.0/umd/react-dom.development.js'
      }

function byVersion (a, b) {
  return semver.lt(a, b) ? -1 : semver.gt(a, b) ? 1 : 0
}

async function getAvailableVersions (packageName, log) {
  const versionsAndTags = await getVersionsAndTags(packageName, log)
  return versionsAndTags ? versionsAndTags.versions.sort(byVersion) : []
}

async function serveBrowsePage (req, res) {
  const availableVersions = await getAvailableVersions(
    req.packageName,
    req.log
  )
  const data = {
    packageName: req.packageName,
    packageVersion: req.packageVersion,
    availableVersions,
    filename: req.filename,
    target: req.browseTarget
  }
  const content = createElement(BrowseApp, data)
  const elements = getScripts('browse', 'iife', globalURLs)

  const { pipe } = renderToPipeableStream(
    createElement(MainTemplate, {
      title: `UNPKG - ${req.packageName}`,
      description: `The CDN for ${req.packageName}`,
      data,
      content,
      elements
    }), {
      onShellReady () {
        res.set({
          'Content-Type': 'text/html; charset=utf-8',
          'Cache-Control': 'max-age=14400', // 4 hours
          'Cache-Tag': 'browse'
        })
        pipe(res)
      }
    }
  )
}

export default asyncHandler(serveBrowsePage)
